package spea.mcMST;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

import mcMST.Graph;
import mcMST.MSTGeneticOperations;
import mcMST.MSTGenotype;

import spea.*;
import common.GeneticHelper;
import common.GeneticOperations;


public class mcMSTRunner {
	private final int PN = 100; // population size
	private final int AN = 100; // archive size;
	private final int T = 20000; // maximum member of generation --- bylo 20000
	private int t = 0;
	private IndividualSet<MSTGenotype> population;
	private IndividualSet<MSTGenotype> archive;
	private IndividualSet<MSTGenotype> newArchive;
	private IndividualSet<MSTGenotype> matingPool;

	//20ms
	private final double timeLimit = 30 * 1000; 
	public double ref_f0 = 100.0;
	public double ref_f1 = 100.0;
	private long begMili;
	private long endMili;



	public mcMSTRunner(GeneticOperations<MSTGenotype> aGo) {
		//this.go = aGo;
		population = new IndividualSet<MSTGenotype>(PN, aGo);
		archive = new IndividualSet<MSTGenotype>(AN, aGo);
	}


	public static void runExperiment(String input, String output, String hvfile) {	
		Graph graph = null;
		try {
			graph = new Graph(input);
		}
		catch (Exception e) { e.printStackTrace(); }

		MSTGeneticOperations go = new MSTGeneticOperations(graph);
		mcMSTRunner mstRunner = new mcMSTRunner(go);

		mstRunner.begMili = System.currentTimeMillis();


		// 1. Generate an initial population and create the empty archive
		mstRunner.population.generateRandomIndividuals();
		mstRunner.t = 0;

		//do zapisywania HV
		BufferedWriter HVout = null;
		try {
			HVout = new BufferedWriter(new FileWriter(hvfile));

			System.out.println("Witaj w SPEA2");
			while (true) {
				// 2. Calculate fitness values of individuals in t - population and
				// t - archive
				mstRunner.population.calculateFitness(mstRunner.archive);


				/*Iterator<Creature> iter;
			  for (iter = salb1Runner.population.iterator(); iter.hasNext(); )
			  {
			      Creature creature = iter.next();
			      System.out.println("f1: " + creature.getf1() + " f2: " + 
			       creature.getf2() + " strenght: " + creature.getStrength() + " row fitnes: " 
			       + creature.getRowFitness() + " density: " +
			         creature.getDensity() + " fitness: " + creature.getFitness() +
			         " dist: " + creature.getDistance()); 
			  }
			  System.out.println(); System.out.println();*/


				// 3. environmental selection
				// Copy all nondominated individuals in t - population and t - archive to t + 1 archive
				mstRunner.newArchive = mstRunner.population.copyNdIndividuals(mstRunner.archive);

				//HVR
				long time = System.currentTimeMillis() - mstRunner.begMili;
				if((mstRunner.t % 10) == 0)
				{
					double HV = GeneticHelper.calculateHiperValume(mstRunner.newArchive.getIndividuals(), mstRunner.ref_f0, mstRunner.ref_f1);
					System.out.println("time " + time + " step "+ mstRunner.t + " HV = " + HV);

					try {
						HVout.write(String.valueOf(time));
						//HVout.write(String.valueOf(mstRunner.t));
						HVout.write(' ');
						HVout.write(String.valueOf(HV));					
						HVout.newLine();
					} catch (IOException e) {
						System.out.println("IOException " + e.getMessage());
					}
				}

				// 4. Set output and termination
				if ((time >= mstRunner.timeLimit) | (mstRunner.t >= mstRunner.T)) {
					try {
						try {
							BufferedWriter out = new BufferedWriter(new FileWriter(
									output));
							for (int i = 0; i < mstRunner.newArchive.getIndividuals().size(); i++) {
								Individual<MSTGenotype> creatureTmp = mstRunner.newArchive.getIndividuals().get(i);
								out.write(String.valueOf(creatureTmp.getValue(0)));
								out.write(' ');
								out.write(String.valueOf(creatureTmp.getValue(1)));					
								out.newLine();
							}
							out.close();

						} catch (FileNotFoundException e) {
							System.out.println("FileNotFoundException " + e);
						}
					} catch (IOException e) {
						System.out.println("IOException " + e);
					}

					if (mstRunner.t == mstRunner.T) {
						System.out.println("Wykonano wszystkie kroki");
					}

					mstRunner.endMili = System.currentTimeMillis();
					System.out.println("Czas trwania " + (mstRunner.endMili - mstRunner.begMili));
					System.out.println("Liczba krokow algorytmu " + mstRunner.t);

					HVout.close();
					return;
				}

				// 5. mating selection
				mstRunner.matingPool = mstRunner.newArchive.matingSelection();

				// 6. variation: recombination and mutation
				mstRunner.matingPool.recombination();
				mstRunner.matingPool.mutation();
				mstRunner.population = mstRunner.matingPool;
				mstRunner.archive = mstRunner.newArchive;
				mstRunner.t++;

				//System.out.println("Iteracja " + mstRunner.t);
			}
		} catch (IOException e1) {
			System.out.println("IOException " + e1.getMessage());
		}
	}


	public static void main(String args[]) {
		mcMSTRunner.runExperiment("inp_mst_100_2.txt", "output/inp_mst_100_2_spea_out.txt", "output/inp_mst_100_2_spea_hv.txt");
	}
}

